import storage from '../../cache/gh-storage';

const DEFAULT_CONFIG = {
  maxConcurrent: 10,
  timeout: 0,
  header: {
    "Content-Type": "application/x-www-form-urlencoded",
    "AppType": "mp",
    "access_token": storage.getUserInfo()['access_token']||''
  },
  dataType: 'json'
};

class GdHttp {
  constructor() { };
  _wx = wx;
  _queue = [];
  _runningTask = 0;
  _maxConcurrent = DEFAULT_CONFIG.maxConcurrent;
  requestInterceptor = (config) => true;
  responseInterceptor = (
    config,
    response
  ) => true;

  _next() {
    const queue = this._queue;

    if (!queue.length || this._runningTask >= this._maxConcurrent) return;

    const entity = queue.shift();
    const config = entity.config;

    const {
      requestInterceptor,
      responseInterceptor
    } = this;

    if (requestInterceptor.call(this, config) !== true) {
      let response = {
        data: null,
        errMsg: `Request Interceptor: Request can\'t pass the Interceptor`,
        statusCode: 0,
        header: {}
      };
      entity.reject(response);
      return;
    }

    this._runningTask = this._runningTask + 1;

    let timer = null;
    let aborted = false;
    let finished = false;

    const callBack = {
      success: (res) => {

        if (aborted) return;
        finished = true;
        timer && clearTimeout(timer);
        entity.response = res;
        if (res.statusCode !== 200) {
          this._wx.showToast({
            title: '请求错误,请您重试',
            icon: "none",
          });
          entity.reject(res)
        } else {
          responseInterceptor.call(this, config, res) !== true ?
            entity.reject(res) :
            entity.resolve(res.data);
        }
      },
      fail: (res) => {

        if (aborted) return;
        finished = true;
        timer && clearTimeout(timer);
        entity.response = res;
        if (res.statusCode !== 200) {
          this._wx.showToast({
            title: '请求错误,请您重试'
          });
          entity.reject(res)
        } else {
          responseInterceptor.call(this, config, res) !== true ?
            entity.reject(res) :
            entity.resolve(res);
        }

      },
      complete: () => {
        if (aborted) return;
        // this.emit('complete', config, entity.response);
        this._next();
        this._runningTask = this.runningTask - 1;
      }
    };

    const requestConfig = Object.assign(config, callBack);
    const task = this._wx.request(requestConfig);

    if (config.timeout > 0) {
      timer = setTimeout(() => {
        if (!finished) {
          aborted = true;
          task && task.abort();
          this._next();
        }
      }, config.timeout);
    }
  };
  request(opts) {
    const config = {
      ...opts,
      header: {
        ...DEFAULT_CONFIG.header,
        ...opts.header,
      },
      dataType: opts.dataType || DEFAULT_CONFIG.dataType,
      timeout: DEFAULT_CONFIG.timeout,
    };
    return new Promise((resolve, reject) => {
      const entity = {
        config,
        resolve,
        reject,
        response: null
      };
      this._queue.push(entity);
      this._next();
    });
  };

  setRequestInterceptor(interceptor) {
    this.requestInterceptor = interceptor;
    return this;
  }
  setResponseInterceptor(interceptor) {
    this.responseInterceptor = interceptor;
    return this;
  }
  clean() {
    this.queue = [];
  }
}

export default new GdHttp();